/*
 * This is the code for the Rear card in the Hybrid Autorickshaw
 * project.
 * 
 * Functionality is to control the rear lights using CAN.
 * 
 * The lights are:
 * Left Indicator		O	PORTC4
 * Right indicator		O	PORTB3
 * 
 * Break Lights			O	PORTC6
 * Rear Lights			O	PORTB4
 * Reversing Light		O	PORTB2
 * Registrationplate	O	PORTC5
 * 
 * Todo:
 * Test everything, implement emergency lights
 */

// Global tinyTimer includes 
#include <tT.h>
#include <env.h>

// Specific includes
#include "can.h"
#include "rear.h"

rear_t rear = {tt_object()};

// Some functions
void rearCan(rear_t *self, can_message_t *msg);
	
can_listener_t listener_rear = {(tt_object_t*)&rear, (tt_method_t)rearCan, ENV_MSEC(10), 0x720, 0x7F0};

void rearInit(rear_t *self, void *none){
	//Enabling Lamps as outputs (PB2,PB3,PB4,PC4,PC5,PC6)
	DDRB	|= (1 << DDB2) | (1 << DDB3) | (1 << DDB4);
	DDRC	|= (1 << DDC4) | (1 << DDC5) | (1 << DDC6);
	
	//We always want to have the rear lights and regristration lights on at startup
	PORTB |= (1<<PINB2);	//Regristration
	PORTC |= (1<<PINC6);	//Rear 
	
	can_listener_t * l = &listener_rear;
	TT_SYNC(&can, canInstall, &l);
}

/*
 Translates the can message to the commands 
 */
void rearCan(rear_t *self, can_message_t *msg) {
	switch (msg->id & 0xF) {
		case 0x1:
			//Turn breakligts on
			TT_ASYNC(self,breakLight,TT_ARGS_NONE);
			self->breakLights = ON;
			break;
		case 0x2:
			//Turn breakligts off
			TT_ASYNC(self,breakLight,TT_ARGS_NONE);
			self->breakLights = OFF;
			break;
		case 0x3:
			//Toggle the ON/OFF state
			if(!self->leftIndicator){
				TT_ASYNC(self,leftRearIndicator,TT_ARGS_NONE);
				self->leftIndicator = ON;
			}				
			break;
		case 0x4:
			//Toggle the ON/OFF state
			if(!self->rightIndicator){
				TT_ASYNC(self,rightRearIndicator,TT_ARGS_NONE);
				self->rightIndicator = ON;
			}				
			break;
		case 0x5:
			self->leftIndicator = OFF;
			self->rightIndicator = OFF;
			TT_ASYNC(self,rightRearIndicator,TT_ARGS_NONE);
			TT_ASYNC(self,leftRearIndicator,TT_ARGS_NONE);
			break;
		case 0x6:
			//Make an asynchronys call to toggle Emergency lights
			if(!self->warningLights){
				TT_ASYNC(self,rearWarningLights,TT_ARGS_NONE);
				self->warningLights = ON;
			}		
			break;
		case 0x7:
			self->warningLights = OFF;
			break;
		case 0x8:
			self->reversingLights = ON;
			TT_ASYNC(self, reversingLight,TT_ARGS_NONE);
			break;
		case 0x9:
			self->reversingLights = OFF;
			TT_ASYNC(self, reversingLight,TT_ARGS_NONE);
			break;
	}
}


/*
 *Function for the braklights 
 */
void breakLight(rear_t *self, void *none){
	if(self->breakLights == ON){
		PORTC &= ~(1<<PINC6);
		PORTB |= (1<<PINB4);	//Turn the breaking lights on
	}else{
		PORTC |= (1<<PINC6);
		PORTB &= ~(1<<PINB4);	//Turn the breaking ligts off
	}
}

void reversingLight(rear_t *self, void *none){
	if(self->reversingLights == ON){
		PORTC |= (1<<PINC5);	//Turn the reversing lights on
	}else{
		PORTC &= ~(1<<PINC5);	//Turn the reversing ligts off
	}
}

/*
 *Function to toggle Left Indicator 
 */
void leftRearIndicator(rear_t *self, void *none){
	if(self->leftIndicator == ON && self->warningLights == OFF){
		PORTC ^= (1<<PINC4); 
		TT_AFTER(ENV_MSEC(500),self,leftRearIndicator,TT_ARGS_NONE);
	}else{
		//Make sure that the lights will stay off when we stop
		if(!self->warningLights)
			PORTC &= ~(1<<PINC4);
	}
}

/*
 *Function to toggle Right Indicator 
 */
void rightRearIndicator(rear_t *self, void *none){
	if(self->rightIndicator == ON && self->warningLights == OFF){
		PORTB ^= (1<<PINB3); 
		TT_AFTER(ENV_MSEC(500),self,rightRearIndicator,TT_ARGS_NONE);
	}else{
		//Make sure that the lights will stay off when we stop
		if(!self->warningLights)
			PORTB &= ~(1<<PINB3);
	}
}

void rearWarningLights(rear_t *self, void *none){
	if(self->warningLights == ON){
		PORTB ^= (1<<PINB3); 
		PORTC ^= (1<<PINC4);
		TT_AFTER(ENV_MSEC(500),self,rearWarningLights,TT_ARGS_NONE);
	}else{
		PORTB &= ~(1<<PINB3);
		PORTC &= ~(1<<PINC4);
	}	
}